home *** CD-ROM | disk | FTP | other *** search
/ Aminet 31 / Aminet 31 (1999)(Schatztruhe)[!][Jun 1999].iso / Aminet / dev / c / vbccwossrc.lha / vbcc / pasm / instructions.c < prev    next >
C/C++ Source or Header  |  1999-03-07  |  44KB  |  1,298 lines

  1. /* $VER: pasm instructions.c V1.2b (01.02.99)
  2.  *
  3.  * This file is part of pasm, a portable PowerPC assembler.
  4.  * Copyright (c) 1997-98  Frank Wille
  5.  *
  6.  * pasm is freeware and part of the portable and retargetable ANSI C
  7.  * compiler vbcc, copyright (c) 1995-98 by Volker Barthelmann.
  8.  * pasm may be freely redistributed as long as no modifications are
  9.  * made and nothing is charged for it. Non-commercial usage is allowed
  10.  * without any restrictions.
  11.  * EVERY PRODUCT OR PROGRAM DERIVED DIRECTLY FROM MY SOURCE MAY NOT BE
  12.  * SOLD COMMERCIALLY WITHOUT PERMISSION FROM THE AUTHOR.
  13.  *
  14.  *
  15.  * v1.2b  (01.02.99) phx
  16.  *        Fixed move_symbols() for move-deltas > alignment (e.g. .align 2)
  17.  * v1.2   (21.10.98) phx
  18.  *        @sdarx support for T_DD- and T_DS-type instructions.
  19.  *        Replaced obsolete R_PPC_TOC16 by real R_PPC_SDAREL16.
  20.  *        Fixed mfdcr and mtdcr.
  21.  * v1.1d  (27.09.98) phx
  22.  *        Optional PPC4xx instructions mfdcr and mtdcr.
  23.  * v1.1a  (20.06.98) phx
  24.  *        F_UPDATE. Check rA = rD for update instructions.
  25.  * v1.1   (19.06.98) phx
  26.  *        Multiple small data sections are supported. The new directive
  27.  *        .sdreg should be used to set the base register.
  28.  *        Fixed "Extra characters on line" error for "la rN,<symbol>".
  29.  *        Wrong error message (46) for "la rN,<absSymbol>". Changed to
  30.  *        error 32: reloc symbol required.
  31.  * v1.0   (21.05.98) phx
  32.  *        tlsync should have been tlbsync.
  33.  *        mtsrin is a supervisor instruction.
  34.  *        ME was not checked for rlwxxx.
  35.  *        mb/me in rldicxx is 6 bit, not 5.
  36.  * v0.9   (07.03.98) phx
  37.  *        Base relative access on external symbol generated wrong
  38.  *        relocation type.
  39.  *        R_ADDR16 relocations in code section had wrong offset.
  40.  *        R_REL14 branches will only get a 2-byte offset, if the output
  41.  *        format is EHF/ADOS and a relocation- or xref-entry is required.
  42.  * v0.8   (14.02.98) phx
  43.  *        Alignment list for each section. This fixes the problems
  44.  *        with optimizations.
  45.  * v0.7   (02.01.98) phx
  46.  *        Implemented optimization OPT_FAR_BRANCH.
  47.  * v0.6   (30.10.97) phx
  48.  *        No more warnings for val@l(rA), where val is > 0x7fff.
  49.  *        Warnings for optional, 64-bit and supervisor instructions
  50.  *        can be suppressed.
  51.  * v0.5   (03.10.97) phx
  52.  *        Auto-converting (rA) into 0(rA) had lead to conflicts with terms.
  53.  *        For example: (x+y)(rA)
  54.  * v0.4   (05.07.97) phx
  55.  *        AA bit in BC instructions is set to allow correct EHF reloction
  56.  *        (by using AmigaDOS HUNK_RELRELOC16. This should be no problem,
  57.  *        because absolute branches are not supported by EHF anyway.
  58.  *        Branch prediction with BCA didn't work correctly.
  59.  *        Relative branches into other sections are allowed, but the
  60.  *        user will be warned, because not all object formats / linkers
  61.  *        support it.
  62.  *        Omitting zero in load/store instructions is allowed, e.g.
  63.  *        "rD,(rA)" will be converted into "rD,0(rA)".
  64.  *        R_PPC_TOC16 support for T_DD- and T_DS-type instructions.
  65.  * v0.3   (05.04.97) phx
  66.  *        An external symbol@l/h/ha, used in d(Rn) addressing mode, got
  67.  *        R_PPC_ADDR16 relocation instead R_PPC_ADDR16_LO/HI/HA.
  68.  *        Little-endian support.
  69.  * v0.2   (25.03.97) phx
  70.  *        Writes ELF object for 32-bit PowerPC big-endian. Either absolute
  71.  *        or ELF output format may be selected. ELF is default for all
  72.  *        currently supported platforms. PPCasm supports nine different
  73.  *        relocation types (there are much more...).
  74.  *        Compiles and works also under NetBSD/amiga (68k).
  75.  *        Changed function declaration to 'new style' in all sources
  76.  *        (to avoid problems with '...' for example).
  77.  *        @l/h/ha is allowed for all displacements.
  78.  * v0.1   (11.03.97) phx
  79.  *        First test version with all PowerPC instructions and most
  80.  *        important directives. Only raw, absolute output.
  81.  *        Although all 32- and 64-bit PowerPC instructions are imple-
  82.  *        mented, too few are really tested till now. I'm expecting many
  83.  *        bugs in this long list.
  84.  *        'la' is the only extended mnemonic, which was implemented as a
  85.  *        real instruction and not by a macro. It is possible to imple-
  86.  *        ment all extended mnemonics here, but it would be much work.
  87.  *        Maybe later, to improve speed. ;)
  88.  * v0.0   (21.02.97) phx
  89.  *        File created.
  90.  */
  91.  
  92.  
  93. #define INSTRUCTIONS_C
  94. #include "ppcasm.h"
  95.  
  96.  
  97. void instr(struct GlobalVars *,struct ParsedLine *);
  98. char *check_comma(char *);
  99. void pcadd(struct GlobalVars *,unsigned long);
  100. void store_byte(struct GlobalVars *,uint8);
  101. void store_half(struct GlobalVars *,uint16);
  102. void store_word(struct GlobalVars *,uint32);
  103. void store_float(struct GlobalVars *,double);
  104. void store_double(struct GlobalVars *,double);
  105. void store_space(struct GlobalVars *,unsigned long);
  106.  
  107. static void opt_far_branch(struct GlobalVars *,struct ParsedLine *,
  108.                            uint32 *,uint32 *,int32 *,char *);
  109. static void swapops(uint32 *,uint32 *);
  110. static int count_operands(struct GlobalVars *,char *);
  111. static bool chk_regindir(char *);
  112. static void move_symbols(struct GlobalVars *,uint32,int32);
  113. static void move_aligned_symbols_offset(struct GlobalVars *,
  114.                                         struct AlignPoint *,uint32,int32);
  115. static void move_aligned_symbols_all(struct GlobalVars *gv,
  116.                                      struct AlignPoint *ap,int32);
  117.  
  118.  
  119.  
  120. struct CPUInstr instructions[] = {
  121.   /* standard PowerPC instruction set */
  122.   { 0,"add",0,T_X,31,0,0,(0<<10)+(266<<1)+0 },
  123.   { 0,"add.",0,T_X,31,0,0,(0<<10)+(266<<1)+1 },
  124.   { 0,"addo",0,T_X,31,0,0,(1<<10)+(266<<1)+0 },
  125.   { 0,"addo.",0,T_X,31,0,0,(1<<10)+(266<<1)+1 },
  126.   { 0,"addc",0,T_X,31,0,0,(0<<10)+(10<<1)+0 },
  127.   { 0,"addc.",0,T_X,31,0,0,(0<<10)+(10<<1)+1 },
  128.   { 0,"addco",0,T_X,31,0,0,(1<<10)+(10<<1)+0 },
  129.   { 0,"addco.",0,T_X,31,0,0,(1<<10)+(10<<1)+1 },
  130.   { 0,"adde",0,T_X,31,0,0,(0<<10)+(138<<1)+0 },
  131.   { 0,"adde.",0,T_X,31,0,0,(0<<10)+(138<<1)+1 },
  132.   { 0,"addeo",0,T_X,31,0,0,(1<<10)+(138<<1)+0 },
  133.   { 0,"addeo.",0,T_X,31,0,0,(1<<10)+(138<<1)+1 },
  134.   { 0,"addi",F_SIGNED,T_DI,14,0,0,0 },
  135.   { 0,"addic",F_SIGNED,T_DI,12,0,0,0 },
  136.   { 0,"addic.",F_SIGNED,T_DI,13,0,0,0 },
  137.   { 0,"addis",F_SIGNED,T_DI,15,0,0,0 },
  138.   { 0,"addme",F_SUPP_B,T_X,31,0,0,(0<<10)+(234<<1)+0 },
  139.   { 0,"addme.",F_SUPP_B,T_X,31,0,0,(0<<10)+(234<<1)+1 },
  140.   { 0,"addmeo",F_SUPP_B,T_X,31,0,0,(1<<10)+(234<<1)+0 },
  141.   { 0,"addmeo.",F_SUPP_B,T_X,31,0,0,(1<<10)+(234<<1)+1 },
  142.   { 0,"addze",F_SUPP_B,T_X,31,0,0,(0<<10)+(202<<1)+0 },
  143.   { 0,"addze.",F_SUPP_B,T_X,31,0,0,(0<<10)+(202<<1)+1 },
  144.   { 0,"addzeo",F_SUPP_B,T_X,31,0,0,(1<<10)+(202<<1)+0 },
  145.   { 0,"addzeo.",F_SUPP_B,T_X,31,0,0,(1<<10)+(202<<1)+1 },
  146.   { 0,"and",F_SWAP,T_X,31,0,0,(28<<1)+0 },
  147.   { 0,"and.",F_SWAP,T_X,31,0,0,(28<<1)+1 },
  148.   { 0,"andc",F_SWAP,T_X,31,0,0,(60<<1)+0 },
  149.   { 0,"andc.",F_SWAP,T_X,31,0,0,(60<<1)+1 },
  150.   { 0,"andi.",F_SWAP,T_DI,28,0,0,0 },
  151.   { 0,"andis.",F_SWAP,T_DI,29,0,0,0 },
  152.   { 0,"b",F_SIGNED,T_I,18,0,0,0 },
  153.   { 0,"bl",F_SIGNED,T_I,18,0,0,1 },
  154.   { 0,"ba",0,T_I,18,0,0,2 },
  155.   { 0,"bla",0,T_I,18,0,0,3 },
  156.   { 0,"bc",F_SIGNED,T_B,16,0,0,0 },
  157.   { 0,"bcl",F_SIGNED,T_B,16,0,0,1 },
  158.   { 0,"bca",0,T_B,16,0,0,2 },
  159.   { 0,"bcla",0,T_B,16,0,0,3 },
  160.   { 0,"bcctr",0,T_XLB,19,0,0,(528<<1)+0 },
  161.   { 0,"bcctrl",0,T_XLB,19,0,0,(528<<1)+1 },
  162.   { 0,"bclr",0,T_XLB,19,0,0,(16<<1)+0 },
  163.   { 0,"bclrl",0,T_XLB,19,0,0,(16<<1)+1 },
  164.   { 0,"cmp",0,T_CMP,31,0,0,(0<<1) },
  165.   { 0,"cmpl",0,T_CMP,31,0,0,(32<<1) },
  166.   { 0,"cmpi",F_SIGNED|F_SUPP_B,T_CMP,11,0,0,0 },
  167.   { 0,"cmpli",F_SUPP_B,T_CMP,10,0,0,0 },
  168.   { 0,"cntlzd",F_SWAP|F_SUPP_B|F_64BIT,T_X,31,0,0,(58<<1)+0 },
  169.   { 0,"cntlzd.",F_SWAP|F_SUPP_B|F_64BIT,T_X,31,0,0,(58<<1)+1 },
  170.   { 0,"cntlzw",F_SWAP|F_SUPP_B,T_X,31,0,0,(26<<1)+0 },
  171.   { 0,"cntlzw.",F_SWAP|F_SUPP_B,T_X,31,0,0,(26<<1)+1 },
  172.   { 0,"crand",0,T_X,19,0,0,(257<<1) },
  173.   { 0,"crandc",0,T_X,19,0,0,(129<<1) },
  174.   { 0,"creqv",0,T_X,19,0,0,(289<<1) },
  175.   { 0,"crnand",0,T_X,19,0,0,(225<<1) },
  176.   { 0,"crnor",0,T_X,19,0,0,(33<<1) },
  177.   { 0,"cror",0,T_X,19,0,0,(449<<1) },
  178.   { 0,"crorc",0,T_X,19,0,0,(417<<1) },
  179.   { 0,"crxor",0,T_X,19,0,0,(193<<1) },
  180.   { 0,"dcbf",F_SUPP_D,T_X,31,0,0,